/* Developed by Vinh, Nguyen Hong <mansofta@gmail.com>
 * Copyright HIENDAI SOFTWARE COMPANY 2004
 * http://www.hiendai.com.vn
 * contact@hiendai.com.vn
*/
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.Collections;
using System.Text.RegularExpressions;

namespace MarcXmlParser {

	public class CRecords
	{	
	protected	XmlDocument ptCurrentDoc;
	protected	XmlNodeList ptCurrentRecordList;		
	protected	static String UpperChars;
	protected	static String LowerChars;
    protected bool _is_Changed = false;
		
	public CRecords()
	{
			
			//Build conversion character string
			UpperChars="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
			LowerChars="abcdefghijklmnopqrstuvwxyz";
			//==========Special Upper Chars
			short[] VietUpperChars=new short[62]{192,193,7842,195,7840,258,7856,7854,7858,7860,
											  7862,194,7846,7844,7848,7850,7852,272,200,201,
											  7866,7868,7864,202,7872,7870,7874,7876,7878,204,
											  205,7880,296,7882,210,211,7886,213,7884,212,
											  7890,7888,7892,7894,7896,416,7900,7898,7902,7904,
											  7906,217,218,7910,360,7908,431,7914,7912,7916,
											  7918,7920};
			//==========Special Lowers Chars
			short[] VietLowerChars=new short[62]{224,225,7843,227,7841,259,7857,7855,7859,7861,
											  7863,226,7847,7845,7849,7851,7853,273,232,233,
											  7867,7869,7864,234,7873,7871,7875,7877,7878,236,
											  237,7881,297,7883,242,243,7887,245,7885,244,
											  7891,7889,7893,7895,7897,417,7901,7899,7903,7905,
											  7907,249,250,7911,361,7909,432,7915,7913,7917,
											  7919,7921};
			StringBuilder Lsb=new StringBuilder(LowerChars);
			StringBuilder Usb=new StringBuilder(UpperChars);
			Char myChar=' ';
			for(int i=0;i<62;i++) //Add Vietnamese characters to string
			{
				myChar=(Char)VietLowerChars[i];
				Lsb.Append(myChar);
				myChar=(Char)VietUpperChars[i];
				Usb.Append(myChar);
			}
			UpperChars=Usb.ToString();
			LowerChars=Lsb.ToString();
			//End build conversion character string

			ptCurrentDoc=new XmlDocument();
            ptCurrentDoc.NodeChanged += new XmlNodeChangedEventHandler(ptCurrentDoc_Changed);
            ptCurrentDoc.NodeInserted += new XmlNodeChangedEventHandler(ptCurrentDoc_Changed);
            ptCurrentDoc.NodeRemoved += new XmlNodeChangedEventHandler(ptCurrentDoc_Changed);		
			ptCurrentDoc.LoadXml("<recordset></recordset>"); 			 
			XmlElement xElem=ptCurrentDoc.DocumentElement;			
			ptCurrentRecordList=xElem.SelectNodes("./*[local-name() ='record']");
		}
    private void ptCurrentDoc_Changed(object sender, EventArgs e)
    {
        _is_Changed = true;
    }
    public bool is_Changed
    {
        get
        {
            return _is_Changed;
        }
        set
        {
            _is_Changed = value;
        }
    }
        
    public void ReConstruct()
		{			
			ptCurrentDoc.LoadXml("<recordset></recordset>"); 
			XmlElement xElem=ptCurrentDoc.DocumentElement;			
			ptCurrentRecordList=xElem.SelectNodes("./*[local-name() ='record']");			
		}

	public  bool load_Xml(String MarcRecordsXml)
		{
			ptCurrentDoc.LoadXml(MarcRecordsXml);
			XmlElement xElem=ptCurrentDoc.DocumentElement;			
			ptCurrentRecordList=xElem.SelectNodes("./*[local-name() ='record']");
			if (ptCurrentRecordList!=null)
				return true;
			else
				return false;
		}	
	public  bool load_File(String XmlFileName)
		{
			XmlTextReader reader = new XmlTextReader(XmlFileName);
			reader.WhitespaceHandling = WhitespaceHandling.None;
            try
            {
                ptCurrentDoc.Load(reader);
                XmlElement xElem = ptCurrentDoc.DocumentElement;
                xElem.RemoveAllAttributes();
                ptCurrentRecordList = xElem.SelectNodes("./*[local-name() = 'record']");
                if (ptCurrentRecordList != null)
                    return true;
                else
                    return false;
            }
            finally
            {
                reader.Close();
            }
		}
	 
	public  bool load_Uri(String XmlUri)
		{
			ptCurrentDoc.Load(XmlUri); 
			XmlElement xElem=ptCurrentDoc.DocumentElement;	
			xElem.RemoveAllAttributes();
			ptCurrentRecordList=xElem.SelectNodes("./*[local-name() = 'record']");
            if (ptCurrentRecordList != null)
				return true;
			else
				return false;
		}

	 public String OuterXml
		 {
			 get
			 {
				return ptCurrentDoc.OuterXml ;  			
			 }	 
		}
	public String XsltFile_Transform(String XslFileName)
		{
            XslCompiledTransform xslt = new XslCompiledTransform();
            //XsltSettings xsltSet=new XsltSettings();
            //xsltSet.EnableScript= true;
            xslt.Load(XslFileName);//, xsltSet,null);
			//// Transform the file and output an HTML string.			
			XmlNodeReader xmlNodeRdr = new XmlNodeReader(ptCurrentDoc); 
			StringBuilder Sb=new StringBuilder();
            XmlWriterSettings xsetting = new XmlWriterSettings();
            xsetting.ConformanceLevel = ConformanceLevel.Auto;
			xslt.Transform(xmlNodeRdr,null, XmlWriter.Create(Sb,xsetting), null);
			return Sb.ToString();	
		}
	public String XsltUri_Transform(String XslUri)
		{			
			XslCompiledTransform xslt = new XslCompiledTransform(); 					
			xslt.Load(XmlReader.Create(XslUri));
			//// Transform the file and output an HTML string.			
			XmlNodeReader xmlNodeRdr = new XmlNodeReader(ptCurrentDoc); 
			StringBuilder Sb=new StringBuilder();			
			xslt.Transform(xmlNodeRdr,null, XmlWriter.Create(Sb), null);
			return Sb.ToString();	
		}
	public void Save(String XmlFileName)
		{	
				ptCurrentDoc.PreserveWhitespace = true;
                XmlWriter xW = XmlWriter.Create(XmlFileName);
				ptCurrentDoc.Save(xW);
                xW.Flush();
                xW.Close();
		}
	public void Refresh()
		{
			XmlElement xElem=ptCurrentDoc.DocumentElement;			
			ptCurrentRecordList=xElem.SelectNodes("./*[local-name() ='record']");
		}
	public int Count
		{
			get
			{
				//XmlElement xElem=ptCurrentDoc.DocumentElement;
				//ptCurrentRecordList=xElem.SelectNodes("./*[local-name() ='record']");
				return ptCurrentRecordList.Count; 
			}
		}
        public void Add(CRecord ptRecord)
		{	
			XmlElement xElem=ptCurrentDoc.DocumentElement;			
			xElem.AppendChild(ptCurrentDoc.ImportNode(ptRecord.RootNode,true));			  			
		}
        public void Remove(int ItemIndex)
		{		
			XmlElement xElem=ptCurrentDoc.DocumentElement;
			xElem.RemoveChild(ptCurrentRecordList.Item(ItemIndex));
			//ptCurrentRecordList=xElem.SelectNodes("./*[local-name() ='record']");
		}
        public void Remove(ref CRecord ptRecord)
		{		
			XmlElement xElem=ptCurrentDoc.DocumentElement;
			xElem.RemoveChild(ptRecord.RootNode);
			//ptCurrentRecordList=xElem.SelectNodes("./*[local-name() ='record']");
		}
        public void Replace(int Index, ref CRecord ptNewRecord)
		{			
			XmlElement xElem=ptCurrentDoc.DocumentElement;
			XmlNode oldNode=(XmlNode)ptCurrentRecordList.Item(Index);
			XmlNode newNode=xElem.AppendChild(ptCurrentDoc.ImportNode(ptNewRecord.RootNode,true));			
			xElem.ReplaceChild(newNode,oldNode);					
			//ptCurrentRecordList=xElem.SelectNodes("./*[local-name() ='record']");			
		}
        public void Replace(ref CRecord ptOldRecord, ref CRecord ptNewRecord)
		{			
			XmlElement xElem=ptCurrentDoc.DocumentElement;
			XmlNode newNode=xElem.AppendChild(ptCurrentDoc.ImportNode(ptNewRecord.RootNode,true));			
			xElem.ReplaceChild(newNode,ptOldRecord.RootNode);					
			//ptCurrentRecordList=xElem.SelectNodes("./*[local-name() ='record']");			
		}

        public CRecord Record(int RecordIndex)
		{
			CRecord ptRecord;
			ptRecord=new CRecord();
            XmlNode myNode = ptCurrentRecordList.Item(RecordIndex);
			ptRecord.load_RootNode(ref myNode); 
			return ptRecord;				
		}
	public void Filter(String strTag1,String strValue1,String strOperator,String strTag2,String strValue2)
		{		
			int iTag1=0;
			int iTag2=0;
			String strOR="or";
			//String strAND="and";
			String strNOT="not";
			String strLeaderSignal="000";
			if(strTag1.Length>0)
			{
				if(strTag1.Length==5)
				{
					iTag1=Convert.ToInt16(strTag1.Substring(0,3));
				} else
				{
					iTag1=Convert.ToInt16(strTag1);
				}
				
			}
			if(strTag2.Length>0)
			{
				if(strTag2.Length==5)
				{
					iTag2=Convert.ToInt16(strTag2.Substring(0,3));
				}else
				{
					iTag2=Convert.ToInt16(strTag2);
				}				
			}
			strOperator=strOperator.ToLower();
			StringBuilder QueryStr = new StringBuilder();
			QueryStr.Append("(./*[local-name() ='record'])[");

			//start with Tag1 and Value1
			if(strTag1.Length==0)//all record content
			{
				QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
				QueryStr.Append(XPathQuoteString(strValue1));
				QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))");

			} else if(strTag1.Equals(strLeaderSignal))//leader
			{
				QueryStr.Append("(./*[local-name() ='leader'])[");				
				QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
				QueryStr.Append(XPathQuoteString(strValue1));
				QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))]");

			} else if((strTag1.Length==3) && (iTag1>=1) && (iTag1<10))//Control fields
			{
				QueryStr.Append("(./*[local-name() ='controlfield'])");
				QueryStr.Append("[@tag='");					
				QueryStr.Append(strTag1);
				QueryStr.Append("' and ");		
				QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
				QueryStr.Append(XPathQuoteString(strValue1));
				QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))]");			
			} else //Datafield
			{
				QueryStr.Append("(./*[local-name() ='datafield'])");
				if(strTag1.Length==3)
				{
					QueryStr.Append("[@tag='");					
					QueryStr.Append(strTag1);
					QueryStr.Append("' and ");
				} else if(strTag1.Length==2)
				{
					QueryStr.Append("[substring(@tag,1,2)='");					
					QueryStr.Append(strTag1);
					QueryStr.Append("' and ");		
				} else if(strTag1.Length==1)		
				{
					QueryStr.Append("[substring(@tag,1,1)='");					
					QueryStr.Append(strTag1);
					QueryStr.Append("' and ");				
				} else if (strTag1.Length==5)//add more for tag|subfield	like 260|a and (./*[local-name() ='subfield'])[@code='
				{
					QueryStr.Append("[@tag='");					
					QueryStr.Append(strTag1.Substring(0,3));
					QueryStr.Append("' and (./*[local-name() ='subfield'])[@code='");
					QueryStr.Append(strTag1.Substring(4,1));
					QueryStr.Append("' and ");				
				}
				QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
				QueryStr.Append(XPathQuoteString(strValue1));
				QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))]");
				if(strTag1.Length==5)
				{
					QueryStr.Append("]");					
				}
			}

			//end with Tag1 and Value1
			if(strOperator.Equals(strOR))
			{
				QueryStr.Append(" or ");
			} else
			{
				QueryStr.Append(" and ");
			}
			//start with Tag2 and Value2
			if(strOperator.Equals(strNOT))
				{
					if(strTag2.Length==0)//all record content
					{
						QueryStr.Append("not(contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
						QueryStr.Append(XPathQuoteString(strValue2));
						QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')))");

					} else if(strTag2.Equals(strLeaderSignal))//leader
					{
						QueryStr.Append("(./*[local-name() ='leader'])[");				
						QueryStr.Append("not(contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
						QueryStr.Append(XPathQuoteString(strValue2));
						QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')))]");

					} else if((strTag2.Length==3) && (iTag2>=1) && (iTag2<10))//Control fields
					{
						QueryStr.Append("(./*[local-name() ='controlfield'])");
						QueryStr.Append("[@tag='");					
						QueryStr.Append(strTag2);
						QueryStr.Append("' and ");		
						QueryStr.Append("not(contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
						QueryStr.Append(XPathQuoteString(strValue2));
						QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')))]");			
					} else //Datafield
					{
						QueryStr.Append("(./*[local-name() ='datafield'])");
						if(strTag2.Length==3)
						{
							QueryStr.Append("[@tag='");					
							QueryStr.Append(strTag2);
							QueryStr.Append("' and ");
						} else if(strTag2.Length==2)
						{
							QueryStr.Append("[substring(@tag,1,2)='");					
							QueryStr.Append(strTag2);
							QueryStr.Append("' and ");		
						} else if(strTag2.Length==1)		
						{
							QueryStr.Append("[substring(@tag,1,1)='");					
							QueryStr.Append(strTag2);
							QueryStr.Append("' and ");				
						} else if(strTag2.Length==5)
						{
							QueryStr.Append("[@tag='");					
							QueryStr.Append(strTag2.Substring(0,3));
							QueryStr.Append("' and (./*[local-name() ='subfield'])[@code='");
							QueryStr.Append(strTag2.Substring(4,1));
							QueryStr.Append("' and ");				
						}
						
						QueryStr.Append("not(contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
						QueryStr.Append(XPathQuoteString(strValue2));
						QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')))]");

						if(strTag2.Length==5)
						{
							QueryStr.Append("]");					
						}

					}
				} else
				{
					if(strTag2.Length==0)//all record content
					{
						QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
						QueryStr.Append(XPathQuoteString(strValue2));
						QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))");

					} else if(strTag2.Equals(strLeaderSignal))//leader
					{
						QueryStr.Append("(./*[local-name() ='leader'])[");				
						QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
						QueryStr.Append(XPathQuoteString(strValue2));
						QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))]");

					} else if((strTag2.Length==3) && (iTag2>=1) && (iTag2<10))//Control fields
					{
						QueryStr.Append("(./*[local-name() ='controlfield'])");
						QueryStr.Append("[@tag='");					
						QueryStr.Append(strTag2);
						QueryStr.Append("' and ");		
						QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
						QueryStr.Append(XPathQuoteString(strValue2));
						QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))]");			
					} else //Datafield
					{
						QueryStr.Append("(./*[local-name() ='datafield'])");
						if(strTag2.Length==3)
						{
							QueryStr.Append("[@tag='");					
							QueryStr.Append(strTag2);
							QueryStr.Append("' and ");
						} else if(strTag2.Length==2)
						{
							QueryStr.Append("[substring(@tag,1,2)='");					
							QueryStr.Append(strTag2);
							QueryStr.Append("' and ");		
						} else if(strTag2.Length==1)		
						{
							QueryStr.Append("[substring(@tag,1,1)='");					
							QueryStr.Append(strTag2);
							QueryStr.Append("' and ");				
						} else if (strTag2.Length==5)
						{
							QueryStr.Append("[@tag='");					
							QueryStr.Append(strTag2.Substring(0,3));
							QueryStr.Append("' and (./*[local-name() ='subfield'])[@code='");
							QueryStr.Append(strTag2.Substring(4,1));
							QueryStr.Append("' and ");				
						}

						QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
						QueryStr.Append(XPathQuoteString(strValue2));
						QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))]");

						if(strTag2.Length==5)
						{
							QueryStr.Append("]");					
						}

					}

				}

			//end with Tag2 and Value2

			QueryStr.Append("]");

			XmlElement xElem=ptCurrentDoc.DocumentElement;		
			ptCurrentRecordList=xElem.SelectNodes(QueryStr.ToString());		
		}


		public void Filter(String strTag,String strValue,bool bEqual)
		{		
			int iTag=0;
			String strLeaderSignal="000";
			if(strTag.Length>0)
			{
				if(strTag.Length==5)
				{
					iTag=Convert.ToInt16(strTag.Substring(0,3));
				}else
				{
					iTag=Convert.ToInt16(strTag);
				}				
			}
			StringBuilder QueryStr = new StringBuilder();
			QueryStr.Append("(./*[local-name() ='record'])[");

			//start with Tag1 and Value1
			if(strTag.Length==0)//all record content
			{
				if(bEqual)
				{
					QueryStr.Append("translate(text(),'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')=translate(");
					QueryStr.Append(XPathQuoteString(strValue));
					QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')");

				} else
				{
					QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
					QueryStr.Append(XPathQuoteString(strValue));
					QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))");
				}

			} else if(strTag.Equals(strLeaderSignal))//leader
			{
				if(bEqual)
				{
					QueryStr.Append("(./*[local-name() ='leader'])[");				
					QueryStr.Append("translate(text(),'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')=translate(");
					QueryStr.Append(XPathQuoteString(strValue));
					QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')]");

				} else
				{
					QueryStr.Append("(./*[local-name() ='leader'])[");				
					QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
					QueryStr.Append(XPathQuoteString(strValue));
					QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))]");
				}

			} else if((strTag.Length==3) && (iTag>=1) && (iTag<10))//Control fields
			{
				QueryStr.Append("(./*[local-name() ='controlfield'])");
				QueryStr.Append("[@tag='");					
				QueryStr.Append(strTag);
				QueryStr.Append("' and ");		
				if(bEqual)
				{
					QueryStr.Append("translate(text(),'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')=translate(");
					QueryStr.Append(XPathQuoteString(strValue));
					QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')]");			
				} else
				{
					QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
					QueryStr.Append(XPathQuoteString(strValue));
					QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))]");			
				}
			} else //Datafield
			{
				QueryStr.Append("(./*[local-name() ='datafield'])");
				if(strTag.Length==3)
				{
					QueryStr.Append("[@tag='");					
					QueryStr.Append(strTag);
					QueryStr.Append("' and ");
				} else if(strTag.Length==2)
				{
					QueryStr.Append("[substring(@tag,1,2)='");					
					QueryStr.Append(strTag);
					QueryStr.Append("' and ");		
				} else if(strTag.Length==1)		
				{
					QueryStr.Append("[substring(@tag,1,1)='");					
					QueryStr.Append(strTag);
					QueryStr.Append("' and ");				
				} else if(strTag.Length==5)
				{
					QueryStr.Append("[@tag='");					
					QueryStr.Append(strTag.Substring(0,3));
					QueryStr.Append("' and (./*[local-name() ='subfield'])[@code='");
					QueryStr.Append(strTag.Substring(4,1));
					QueryStr.Append("' and ");				
				}
				if(bEqual)
				{
					QueryStr.Append("translate(text(),'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')=translate(");
					QueryStr.Append(XPathQuoteString(strValue));
					QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("')]");
				}else
				{
					QueryStr.Append("contains(translate(.,'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'),translate(");
					QueryStr.Append(XPathQuoteString(strValue));
					QueryStr.Append(",'"); QueryStr.Append(UpperChars); QueryStr.Append("','"); QueryStr.Append(LowerChars); QueryStr.Append("'))]");
				}
				if(strTag.Length==5)
				{
					QueryStr.Append("]");					
				}
			}

			QueryStr.Append("]");
			XmlElement xElem=ptCurrentDoc.DocumentElement;		
			ptCurrentRecordList=xElem.SelectNodes(QueryStr.ToString());								
		}

        public void Filter(String strTag, String strSubfieldCode, String strValue, bool bEqual)
		{		
			StringBuilder QueryStr = new StringBuilder();
			QueryStr.Append("(./*[local-name() ='record'])[(./*[local-name() ='datafield'])");
			if(strTag.Length==3)
			{
				QueryStr.Append("[@tag='");					
				QueryStr.Append(strTag);
				QueryStr.Append("' and (./*[local-name() ='subfield'])[@code='");
			} else if(strTag.Length==2)
			{
				QueryStr.Append("[substring(@tag,1,2)='");					
				QueryStr.Append(strTag);
				QueryStr.Append("' and (./*[local-name() ='subfield'])[@code='");		
			} else if(strTag.Length==1)		
			{
				QueryStr.Append("[substring(@tag,1,1)='");					
				QueryStr.Append(strTag);
				QueryStr.Append("' and (./*[local-name() ='subfield'])[@code='");				
			}
			QueryStr.Append(strSubfieldCode);

			if(bEqual)
			{
				QueryStr.Append("' and (translate(text(),'");
				QueryStr.Append(UpperChars);
				QueryStr.Append("','");
				QueryStr.Append(LowerChars);
				QueryStr.Append("')=translate(");
				QueryStr.Append(XPathQuoteString(strValue));
				QueryStr.Append(",'");
				QueryStr.Append(UpperChars);
				QueryStr.Append("','");
				QueryStr.Append(LowerChars);
				QueryStr.Append("'))]]]");
			} else
			{
				QueryStr.Append("' and contains(translate(.,'");
				QueryStr.Append(UpperChars);
				QueryStr.Append("','");
				QueryStr.Append(LowerChars);
				QueryStr.Append("'),translate(");
				QueryStr.Append(XPathQuoteString(strValue));
				QueryStr.Append(",'");
				QueryStr.Append(UpperChars);
				QueryStr.Append("','");
				QueryStr.Append(LowerChars);
				QueryStr.Append("'))]]]");
			}

			XmlElement xElem=ptCurrentDoc.DocumentElement;		
			ptCurrentRecordList=xElem.SelectNodes(QueryStr.ToString());				
		}
		//03-01-2007
		//Solve single quote and double qoute
        public static String XPathQuoteString(String inputstr)
		{
			StringBuilder outputstr=new StringBuilder();
			int q1=inputstr.IndexOf("\'");
			int q2=inputstr.IndexOf("\"");
			if((q1<0) && (q2<0))//no quotation marks
			{
				outputstr.Append("\'");
				outputstr.Append(inputstr);
				outputstr.Append("\'");			
			}else if((q1>=0) && (q2<0)) //only single quote
			{
					Regex regex = new Regex("\'");
					String[] tokens = regex.Split(inputstr);
					outputstr.Append("concat(");
					outputstr.Append("\'");
					outputstr.Append(tokens[0]); 
					outputstr.Append("\'");
					for (int i=1; i<tokens.Length; i++)
					{
						outputstr.Append(",");
						outputstr.Append("\"\'\"");
						outputstr.Append(",");
						outputstr.Append("\'");
						outputstr.Append(tokens[i]); 
						outputstr.Append("\'");
					}
					outputstr.Append(")");
			}else if((q1<0) && (q2>=0))
			{
					Regex regex = new Regex("\"");
					String[] tokens = regex.Split(inputstr);
					outputstr.Append("concat(");
					outputstr.Append("\'");
					outputstr.Append(tokens[0]); 
					outputstr.Append("\'");
					for (int i=1; i<tokens.Length; i++)
					{
						outputstr.Append(",");
						outputstr.Append("\'\"\'");
						outputstr.Append(",");
						outputstr.Append("\'");
						outputstr.Append(tokens[i]); 
						outputstr.Append("\'");
					}
					outputstr.Append(")");				
			}else if((q1>=0) && (q2>=0))
			{
				//solve single quote first and double quote inside
					Regex regex = new Regex("\'");
					String[] tokens = regex.Split(inputstr);
					outputstr.Append("concat(");
					//outputstr.Append("\'");
					outputstr.Append(SolveDoubleQoute(tokens[0])); 
					//outputstr.Append("\'");
					for (int i=1; i<tokens.Length; i++)
					{
						outputstr.Append(",");
						outputstr.Append("\"\'\"");
						outputstr.Append(",");
						//outputstr.Append("\'");
						outputstr.Append(SolveDoubleQoute(tokens[i])); 
						//outputstr.Append("\'");
					}
					outputstr.Append(")");				
			}
			return outputstr.ToString();
		}
		//inside concat of single quote add double quotes	
        public static String SolveDoubleQoute(String dbquotesstr)
		{
			StringBuilder outputstr=new StringBuilder();
			Regex regex = new Regex("\"");
			String[] tokens = regex.Split(dbquotesstr);
			if(tokens.Length==1)
			{
				outputstr.Append("\'");
				outputstr.Append(dbquotesstr);
				outputstr.Append("\'");
			}else
			{
				outputstr.Append("\'");
				outputstr.Append(tokens[0]); 
				outputstr.Append("\'");
				for (int i=1; i<tokens.Length; i++)
				{
					outputstr.Append(",");
					outputstr.Append("\'\"\'");
					outputstr.Append(",");
					outputstr.Append("\'");
					outputstr.Append(tokens[i]); 
					outputstr.Append("\'");
				}
			}
			return outputstr.ToString();
		}

	};
}
